package nrpc.register;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import nrpc.message.meta.ServerEntry;

public class ServiceEntry {

	// 检查节点是否活跃间隔
	private static final long CHECK_TIME = 10000;
	// 节点非活跃阈值
	private static final long TIMEOUT = 30000;
	
	private volatile long serverId = 1, subscriberId = 1;
	
	private volatile boolean alive = true;
	
	private Map<Long, ServerEntry> serverMap = new HashMap<>();
	
	private Map<Long, Subscriber> subscriberMap = new ConcurrentHashMap<>();

	public ServiceEntry() {
		new Thread() {
			@Override
			public void run() {
				// 检查服务节点是否活跃
				while(alive){
					try {
						Thread.sleep(CHECK_TIME);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					List<Long> toDelete = new ArrayList<>();
					synchronized(ServiceEntry.this){
						Long current = System.currentTimeMillis();
						serverMap.forEach((id, serverEntry)->{
							if(current - serverEntry.lastActive > TIMEOUT)
								toDelete.add(id);
						});
						toDelete.forEach(ServiceEntry.this::deleteServerEntry);
					}
				}
			}
		}.start();
	}
	
	public synchronized long addServerEntry(ServerEntry serverEntry) {
		this.serverMap.put(serverId, serverEntry);
		subscriberMap.forEach((id, x)->{
			x.getHandler().addServer(serverId, serverEntry);
		});
		return serverId++;
	}
	
	public synchronized void deleteServerEntry(long id) {
		subscriberMap.forEach((sid, x)->{
			x.getHandler().deleteServer(id);
		});
		serverMap.remove(id);
	}
	
	public synchronized void pulse(long id){
		serverMap.get(id).lastActive = System.currentTimeMillis();
	}
	
	public long subscribe(String host, int port){
		Subscriber n = new Subscriber(host, port);
		this.subscriberMap.put(subscriberId, n);
		synchronized(this){
			this.serverMap.forEach((id, x)->{
				n.getHandler().addServer(id, x);
			});
		}
		return subscriberId++;
	}
	
	public void cancelSubscribe(long id){
		this.subscriberMap.remove(id).close();
	}
	
	public void close(){
		subscriberMap.forEach((id, x)->x.close());
		alive = false;
	}
	
}
